#include "uart.h"

int set_serial(int serial_port, int nSpeed, int nBits, char nEvent, int nStop)
{
    int serial_fd;
    char name[20] = {0};
    struct termios newttys1,oldttys1;

    //check串口号
    if (serial_port == 1) {
        memcpy(name, UART_SERIAL_PORT1, sizeof(UART_SERIAL_PORT1));
    } else if (serial_port == 2) {
        memcpy(name, UART_SERIAL_PORT2, sizeof(UART_SERIAL_PORT2));
    } else {
        perror("串口号不存在");
        exit(-1);
    }
    
     // 打开串口设备
    if ((serial_fd = open(name, O_RDWR | O_NOCTTY)) == -1) {
        perror("无法打开串口");
        exit(-1);
    }

     /*保存原有串口配置*/
    if(tcgetattr(serial_fd, &oldttys1)!=0) 
    {
        perror("Setupserial 1");
        return -1;
    }

    bzero(&newttys1, sizeof(newttys1));
    newttys1.c_cflag |= (CLOCAL|CREAD ); /*CREAD 开启串行数据接收，CLOCAL并打开本地连接模式*/
    newttys1.c_cflag &= ~CRTSCTS; // 关闭 RTS/CTS 流控制

    newttys1.c_cflag &= ~CSIZE;/*设置数据位 8位*/
    /*数据位选择*/
    switch (nBits)
    {
        case 7:
            newttys1.c_cflag |= CS7;
            break;
        case 8:
            newttys1.c_cflag |= CS8;
            break;
    }
     /*设置奇偶校验位*/
    switch( nEvent )
    {
        case '0':  /*奇校验*/
            newttys1.c_cflag |= PARENB;/*开启奇偶校验*/
            newttys1.c_iflag |= (INPCK | ISTRIP);/*INPCK打开输入奇偶校验；ISTRIP去除字符的第八个比特  */
            newttys1.c_cflag |= PARODD;/*启用奇校验(默认为偶校验)*/
            break;
        case 'E':/*偶校验*/
            newttys1.c_cflag |= PARENB; /*开启奇偶校验  */
            newttys1.c_iflag |= ( INPCK | ISTRIP);/*打开输入奇偶校验并去除字符第八个比特*/
            newttys1.c_cflag &= ~PARODD;/*启用偶校验*/
            break;
        case 'N': /*无奇偶校验*/
            newttys1.c_cflag &= ~PARENB;
            break;
    }
     /*设置波特率*/
    switch( nSpeed )  
    {
        case 2400:
            cfsetispeed(&newttys1, B2400);
            cfsetospeed(&newttys1, B2400);
            break;
        case 4800:
            cfsetispeed(&newttys1, B4800);
            cfsetospeed(&newttys1, B4800);
            break;
        case 9600:
            cfsetispeed(&newttys1, B9600);
            cfsetospeed(&newttys1, B9600);
            break;
        case 115200:
            cfsetispeed(&newttys1, B115200);
            cfsetospeed(&newttys1, B115200);
            break;
        case 460800:
            cfsetispeed(&newttys1, B460800);
            cfsetospeed(&newttys1, B460800);
            break;
        default:
            cfsetispeed(&newttys1, B9600);
            cfsetospeed(&newttys1, B9600);
            break;
    }
     /*设置停止位*/
    if( nStop == 1)/*设置停止位；若停止位为1，则清除CSTOPB，若停止位为2，则激活CSTOPB*/
    {
        newttys1.c_cflag &= ~CSTOPB;/*默认为一位停止位； */
    }
    else if( nStop == 2)
    {
        newttys1.c_cflag |= CSTOPB;/*CSTOPB表示送两位停止位*/
    }

    /*设置最少字符和等待时间，对于接收字符和等待时间没有特别的要求时*/
    newttys1.c_cc[VTIME] = 0;/*非规范模式读取时的超时时间；*/
    newttys1.c_cc[VMIN]  = 0; /*非规范模式读取时的最小字符数*/
    tcflush(serial_fd , TCIFLUSH);/*tcflush清空终端未完成的输入/输出请求及数据；TCIFLUSH表示清空正收到的数据，且不读取出来 */

     /*激活配置使其生效*/
    if((tcsetattr(serial_fd, TCSANOW, &newttys1))!=0)
    {
        perror("com set error");
        return -1;
    }

    return serial_fd;
}

int init_serial()
{   

	//串口1和串口2参数设置函数
	serial_info.serial_fd1 = set_serial(SERIAL_PORT1, 460800, 8, 'N', 1);   //串口1初始化 /dev/ttyS1
    if (serial_info.serial_fd1 == -1){
        return -1;
    }
	serial_info.serial_fd2 = set_serial(SERIAL_PORT2, 460800, 8, 'N', 1);   //串口2初始化 /dev/ttyS3
    if (serial_info.serial_fd2 == -1){
        return -1;
    }

    return 0;
}

timer_t timers[NUM_TIMERS];
long int set_timer[NUM_TIMERS] = {5000000, 10000000, 100000000, 200000000};

int create_timers()
{
	struct sigevent sev; 
	struct itimerspec its; 
	struct sigaction sa; 

	// Set up signal handler 
	sa.sa_flags  = SA_SIGINFO; 
	sa.sa_sigaction  = timer_handler; 
	sigemptyset(&sa.sa_mask);  
	if (sigaction(SIGRTMIN, &sa, NULL) == -1) { 
		perror("sigaction"); 
		return -1; 
	} 

	// Create timers 
	for (int i = 0; i < NUM_TIMERS; i++) { 
		sev.sigev_notify  = SIGEV_SIGNAL; 
		sev.sigev_signo  = SIGRTMIN; 
		sev.sigev_value.sival_ptr  = &timers[i]; 
		if (timer_create(CLOCK_REALTIME, &sev, &timers[i]) == -1) { 
			perror("timer_create"); 
			return -1; 
		} 

		// Set timer intervals 
		its.it_value.tv_sec  = 1; // Start after 1, 2, 3 seconds 
		its.it_value.tv_nsec  = 0; 
		its.it_interval.tv_sec  = 0; // Repeat every 1, 2, 3 seconds 
		its.it_interval.tv_nsec  = set_timer[i]; 

		if (timer_settime(timers[i], 0, &its, NULL) == -1) { 
			perror("timer_settime"); 
			return -1;
		} 
	} 

    return 0;
}